package org.mashart.pink.m.gps;

/**
 * Simple GPS info aggregation class. No methods, just public attributes
 */
public class Waypoint {
    /**
     * UTC time stamp. No date info.
     * e.g. GPGGA has only this but not date
     */
    public String utc;

    /**
     * Elapsed milliseconds from 00:00:00.000 of today
     */
    public int timeMS;

    /**
     * some other formats, like GPRMC has date field too
     */
    public String date;

    /**
     * Obiuosly, Latitude
     * TODO do we need double or float would be just fine?
     */
    public double latitude;

    /**
     * Longitude
     * TODO do we need double or float would be just fine?
     */
    public double longitude;

    /**
     * Height
     */
    public float altitude;

    /**
     * Velocity
     */
    public float speed;

    /**
     * True - North, false - South
     */
    public boolean ns;

    /**
     * True - East, false - West
     */
    public boolean ew;

    /**
     * false - no fix (prob. not enought satellites, bad coverage); data NOT valid
     * true - data are valid
     */
    public boolean fix;

    /**
     * Number of satellites, usually from 0 to 12
     */
    public short satellites;

    /**
     * Horizontal Dilution Of Precision
     * @see http://en.wikipedia.org/wiki/Dilution_of_precision_(GPS)
     */
    public float hdop;

    /**
     * Vertical Dilution Of Precision
     * @see http://en.wikipedia.org/wiki/Dilution_of_precision_(GPS)
     */
    public float vdop;

    /**
     * Some NMEA sentence format have Units
     * TODO do we need this? Reply: this is only used for altitude. Usaually 'M' (meter) is used. Not sure if there is other unit in use.
     */
    public Character units;

    /**
     * Empty constructor
     */
    public Waypoint() {
        // -1 means timestamp not initilazed yet
        timeMS = -1;
        // "|=" is used to decide if the waypoint is fixed
        fix = false;
    }

    /**
     * Used by Receiver class to display text on device screen
     * about collected GPS info
     *
     * Useful for testing
     */
    public String toString() {
        char ch_ns = ns ? 'N' : 'S';
        char ch_ew = ew ? 'E' : 'W';
        char ch_fix = fix ? 'Y' : 'N';

        StringBuffer buf = new StringBuffer();

        buf.append("UTC: ");
        // if date is unavailable
        if(date != null){
          String str_date = date.substring(0,2) + '/' + date.substring(2,4) + '/' + date.substring(4,6);
          buf.append( str_date ).append(" ");
        }
        buf.append( timeMStoString(timeMS, true) ).append('\n');

        buf.append("Lat: ").append(ch_ns).append(latitude).append('\n');
        buf.append("Lng: ").append(ch_ew).append(longitude).append('\n');
        buf.append("Alt: ").append(altitude).append('\n');
        buf.append("Speed: ").append(speed).append(" km/h").append('\n');
        buf.append("HDOP: ").append(hdop).append(" m").append('\n');
        buf.append("VDOP: ").append(vdop).append(" m").append('\n');
        buf.append("Satellites Number/Fixed: ").append(satellites).append('/').append(ch_fix).append('\n');

        return buf.toString();
    }

    /**
     * Get bytes, which are ready to send out.
     * @return bytes
     */
    public String toHttpQuery(){
        StringBuffer data = new StringBuffer();
        String t = timeMStoString(timeMS, false);
        data.append("t=").append(t).append("&lat=").append(latitude).append("&lng=").append(longitude);
        data.append("&alt=").append(altitude).append("&vdop=").append(vdop).append("&v=").append(speed);
        return data.toString();
    }

    /**
     * Get the string representing elapsed milliseconds
     */
    public static String timeMStoString(int ms, boolean full){
        if(ms < 0){
            return null;
        }

        int hh = (int) ms / 3600000;
        int r2 = ms - 3600000 * hh;

        int mm = (int) r2 / 60000;
        int r3 = r2 - 60000 * mm;

        int ss = (int) r3 / 1000;
        int mmm = r3 - 1000 * ss;

        StringBuffer s = new StringBuffer();

        if(hh < 10){
            s.append(0);
        }
        s.append(hh);

        if(full){s.append(":");}

        if(mm < 10){
            s.append(0);
        }
        s.append(mm);

        if(full){s.append(":");}

        if(ss < 10){
            s.append("0");
        }
        s.append(ss);

        if(full){s.append(".");}

        if(mmm < 100){
            s.append("0");
            if(mmm < 10){
                s.append("0");
            }
        }
        s.append(mmm);

        return s.toString();
    }
}